package com.jinzhending.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @ProjectName: LieIdle
 * @Package: com.jinzhending.utils
 * @Author: huat
 * @Date: 2020/4/8 17:09
 * @Version: 1.0
 */
public class RsaUtil {
    private final static int DEFAULT_KEY_SIZE=2048;
    /**
     * 根据密文，生成rea公钥和私钥，并写入指定文件
     * @param publicKeyFileName 公钥文件路径
     * @param privateKeyFileName 私钥文件路径
     * @param secret 盐
     * @param keySize 大小
     */
    public static void generateKey(String publicKeyFileName,String privateKeyFileName,String secret, int keySize) throws NoSuchAlgorithmException, IOException {
        KeyPairGenerator keyPairGenerator= KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom=new SecureRandom(secret.getBytes());
        keyPairGenerator.initialize(Math.max(keySize,DEFAULT_KEY_SIZE),secureRandom);
        KeyPair keyPair=keyPairGenerator.genKeyPair();
        //获取公钥并写出
        byte[] publicKeyByte=keyPair.getPublic().getEncoded();
        publicKeyByte= Base64.getEncoder().encode(publicKeyByte);
        writeFile(publicKeyFileName,publicKeyByte);
        //获取公钥并写入
        byte[] privateKeyByte=keyPair.getPrivate().getEncoded();
        privateKeyByte= Base64.getEncoder().encode(privateKeyByte);
        writeFile(privateKeyFileName,privateKeyByte);
    }

    /**
     * 获取秘钥
     * @param bytes 秘钥的字节形式
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    private static PrivateKey getPrivateKey(byte[] bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
        bytes=Base64.getDecoder().decode(bytes);
        PKCS8EncodedKeySpec spec=new PKCS8EncodedKeySpec(bytes);
        KeyFactory keyFactory=KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(spec);
    }
    /**
     * 获取公钥
     * @param bytes 公钥的字节形式
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    private static PublicKey getPublicKey(byte[] bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
        bytes=Base64.getDecoder().decode(bytes);
        X509EncodedKeySpec spec=new X509EncodedKeySpec(bytes);
        KeyFactory keyFactory=KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(spec);
    }

    /**
     * 从文件中读取公钥
     * @param fileName 公钥保存路径 相对于classpath
     * @return 公钥对象
     * @throws InvalidKeySpecException
     * @throws NoSuchAlgorithmException
     */
    public static PublicKey getPublicKey(String fileName) throws InvalidKeySpecException, NoSuchAlgorithmException, IOException {
        byte[] bytes=readFile(fileName);
        return getPublicKey(bytes);
    }
    /**
     * 从文件中读取公钥
     * @param fileName 公钥保存路径 相对于classpath
     * @return 私钥对象
     * @throws InvalidKeySpecException
     * @throws NoSuchAlgorithmException
     */
    public static PrivateKey getPrivateKey(String fileName) throws InvalidKeySpecException, NoSuchAlgorithmException, IOException {
        byte[] bytes=readFile(fileName);
        return getPrivateKey(bytes);
    }
    private static byte[] readFile(String fileName) throws IOException {
        return Files.readAllBytes(new File(fileName).toPath());
    }
    private static void writeFile(String fileName,byte[] bytes) throws IOException {
        File file=new File(fileName);
        if(!file.exists()){
            file.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream( fileName);
        fos.write(bytes);
        fos.close();

    }

    public static void main(String[] args) {
        try {
            generateKey("E:\\test\\public.pub","E:\\test\\private","jinzhending,@,",2048);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
